package com.sky.service.impl;


import cn.dev33.satoken.stp.StpUtil;
import cn.mybatis.mp.core.mybatis.mapper.context.Pager;
import cn.mybatis.mp.core.sql.executor.SubQuery;
import cn.mybatis.mp.core.sql.executor.chain.QueryChain;
import cn.mybatis.mp.core.sql.executor.chain.UpdateChain;
import com.sky.constant.MessageConstant;
import com.sky.constant.PopularityScoreConstant;
import com.sky.constant.RedisKeyConstant;
import com.sky.constant.UserActionConstant;
import com.sky.dto.*;
import com.sky.entity.Bookcategories;
import com.sky.entity.Books;
import com.sky.entity.Categories;
import com.sky.entity.Usercollections;
import com.sky.entity.UserBookRatings;
import com.sky.exception.BaseException;
import com.sky.mapper.BookcategoriesMapper;
import com.sky.mapper.BooksMapper;
import com.sky.mapper.CategoriesMapper;
import com.sky.mapper.UsercollectionsMapper;
import com.sky.mapper.UserBookRatingsMapper;
import com.sky.service.*;
import com.sky.vo.*;
import db.sql.api.impl.cmd.basic.OrderByDirection;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import java.util.Collections;
import java.time.LocalDateTime;
import java.time.ZoneId;

/**
 * @author majun
 * @package com.sky.service.impl
 * @date 2024/11/30 11:51
 */
@Service
@Log4j2
public class BookServiceImpl implements BookService {

    @Autowired
    private BooksMapper booksMapper;

    @Autowired
    private BookcategoriesMapper bookcategoriesMapper;

    @Autowired
    private CategoriesMapper categoriesMapper;

    @Autowired
    private CategoriesService categoriesService;

    @Autowired
    private RecommendationService recommendationService;

    @Autowired
    private UsercollectionsMapper usercollectionsMapper;

    @Autowired
    private UserBookRatingsMapper userBookRatingsMapper;

    @Autowired
    private UserbookratingsService userbookratingsService;

    @Autowired
    private UsercollectionsService usercollectionsService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 根据书名，作者名，分页查询图书信息
     *
     * @param getBookPagerDTO 需求的参数（每页条数，页码，书名，作者名）
     * @return 书籍分页信息
     */
    public Pager<BooksVO> getBooksPager(GetBookPagerDTO getBookPagerDTO) {
        // 使用 QueryChain 进行分页查询
        Pager<Books> booksPager = QueryChain.of(booksMapper)
                .select(Books.class)
                .from(Books.class)
                .like(Books::getTitle, getBookPagerDTO.getTitle()) // 通过书名进行模糊查询
                .like(Books::getAuthor, getBookPagerDTO.getAuthor()) // 通过作者名进行模糊查询
                .orderBy(Books::getBookId)  // 按照 bookId 排序
                .paging(Pager.of(getBookPagerDTO.getPageNumber(), getBookPagerDTO.getPageSize())); // 设置分页参数

        // 为每本书查询分类名称并转换为BooksPageVO
        List<BooksVO> booksVOList = booksPager.getResults().stream()
                .map(book -> convertToBooksPageVO(book))
                .collect(Collectors.toList()); // 将处理后的结果转为 List

        // 将处理后的书籍信息（包括分类名称）设置回分页对象
        Pager<BooksVO> pager = new Pager<>();
        BeanUtils.copyProperties(booksPager, pager, "results"); // 复制分页信息
        pager.setResults(booksVOList); // 设置转换后的结果

        // 返回分页查询结果
        return pager;
    }

    /**
     * 图书信息修改
     *
     * @param upBookDTO 图书相关内容
     */
    @Transactional
    public void upBook(UpBookDTO upBookDTO) {

        if (upBookDTO == null) {
            throw new BaseException(MessageConstant.THE_SUBMISSION_CANNOT_BE_EMPTY);
        }

        //修改图书分类
        //根据分类名称查询分类ID
        Categories categories = categoriesMapper.get(where -> {
            where.eq(Categories::getCategoryName, upBookDTO.getCategoryName());
        });
        //实例化表单实体类
        Bookcategories bookcategories = new Bookcategories();
        bookcategories.setBookId(upBookDTO.getBookId());
        bookcategories.setCategoryId(categories.getCategoryId());
        //提价修改
        UpdateChain.of(bookcategoriesMapper)
                .update(Bookcategories.class)
                .set(Bookcategories::getCategoryId, categories.getCategoryId())
                .eq(Bookcategories::getBookId, upBookDTO.getBookId())
                .execute();

        //修改除分类的其他数据
        Books books = new Books();

        BeanUtils.copyProperties(upBookDTO, books);

        booksMapper.update(books);

    }

    /**
     * 图书删除
     *
     * @param bookId 图书ID
     */
    @Transactional
    public void deleteBook(Integer bookId) {

        Books books = booksMapper.get(where -> {
            where.eq(Books::getBookId, bookId);
        });

        if (books == null) {
            throw new BaseException(MessageConstant.BOOK_NOT_FOUND);
        }

        //删除关联的分类信息
        bookcategoriesMapper.delete(where -> {
            where.eq(Bookcategories::getCategoryId, bookId);
        });

        //删除图书信息
        booksMapper.delete(where -> {
            where.eq(Books::getBookId, bookId);
        });

    }

    /**
     * 新增图书
     *
     * @param upBookDTO 图书信息
     */
    @Transactional
    public void saveBook(UpBookDTO upBookDTO) {

        if (upBookDTO == null) {
            throw new BaseException(MessageConstant.THE_SUBMISSION_CANNOT_BE_EMPTY);
        }

        Books oldBook = booksMapper.get(where -> {
            where.eq(Books::getTitle, upBookDTO.getTitle());
        });

        if (oldBook != null) {
            throw new BaseException("书名已存在");
        }

        //先添加图书信息
        Books books = new Books();
        BeanUtils.copyProperties(upBookDTO, books);
        books.setBookId(null);
        books.setPopularityScore(Double.valueOf(PopularityScoreConstant.POPULARITY_SCORE));

        booksMapper.save(books);

        //查询新增图书的ID
        Books newBook = booksMapper.get(where -> {
            where.eq(Books::getTitle, upBookDTO.getTitle());
        });

        Integer bookId = newBook.getBookId();

        //添加图书分类关联信息
        //查询分类ID
        Categories categories = categoriesService.getCategoriesByName(upBookDTO.getCategoryName());

        Bookcategories bookcategories = new Bookcategories();

        bookcategories.setBookId(bookId);
        bookcategories.setCategoryId(categories.getCategoryId());

        bookcategoriesMapper.save(bookcategories);

    }

    /**
     * 获取图书详细信息
     * 包含图书基本信息和分类信息
     *
     * @param bookId 图书ID
     * @return 图书详细信息VO对象
     */
    @Override
    public BooksVO getBooksDetails(Integer bookId) {
        // 1. 查询图书基本信息
        Books book = QueryChain.of(booksMapper)
                .eq(Books::getBookId, bookId)
                .get();

        if (book == null) {
            throw new BaseException(MessageConstant.BOOK_NOT_FOUND);
        }

        // 2. 转换为VO对象并添加分类信息
        BooksVO booksVO = convertToBooksPageVO(book);

        // 3. 记录查看行为（异步）
        try {
            recommendationService.recordUserAction(
                    StpUtil.getLoginIdAsInt(),
                    bookId,
                    UserActionConstant.VIEW
            );
        } catch (Exception e) {
            // 记录行为失败不影响主流程
            log.error("记录查看行为失败 - 图书ID: {}", bookId, e);
        }

        return booksVO;
    }

    /**
     * 根据分类和字数条件分页查询图书
     *
     * @param bookFilterDTO 查询条件（分类ID、字数范围、排序方式等）
     * @return 分页的图书信息
     */
    @Override
    public Pager<BookFilterVO> getBooksByFilter(BookFilterDTO bookFilterDTO) {
        // 1. 构建缓存key
        String cacheKey = String.format("%s:%s:%s:%s:%s:%s:%s:%s",
                RedisKeyConstant.BOOK_FILTER,
                bookFilterDTO.getCategoryId(),
                bookFilterDTO.getMinWordCount(),
                bookFilterDTO.getMaxWordCount(),
                bookFilterDTO.getOrderBy(),
                bookFilterDTO.getOrderDirection(),
                bookFilterDTO.getPageNumber(),
                bookFilterDTO.getPageSize());

        // 2. 尝试从缓存获取
        BookFilterCache cachedResult = (BookFilterCache) redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            return convertCacheToPage(cachedResult);
        }

        // 3. 缓存未命中，从数据库查询
        List<Integer> bookIds = null;
        if (bookFilterDTO.getCategoryId() != null) {
            bookIds = QueryChain.of(bookcategoriesMapper)
                    .ignoreNullValueInCondition(true)
                    .ignoreEmptyInCondition(true)
                    .trimStringInCondition(true)
                    .select(Bookcategories::getBookId)
                    .eq(Bookcategories::getCategoryId, bookFilterDTO.getCategoryId())
                    .list()
                    .stream()
                    .map(Bookcategories::getBookId)
                    .collect(Collectors.toList());

            if (bookIds.isEmpty()) {
                return getEmptyPager(bookFilterDTO.getPageNumber(), bookFilterDTO.getPageSize());
            }
        }

        // 4. 查询图书列表
        QueryChain<Books> queryChain;
        if (bookFilterDTO.getOrderBy() != null && bookFilterDTO.getOrderBy() == 1) {
            // 按收藏数量排序的逻辑
            queryChain = buildCollectionCountQuery(bookIds, bookFilterDTO);
        } else {
            // 按总字数排序的逻辑
            queryChain = buildWordCountQuery(bookIds, bookFilterDTO);
        }

        // 5. 执行分页查询
        Pager<Books> booksPager = queryChain.paging(
                Pager.of(bookFilterDTO.getPageNumber(), bookFilterDTO.getPageSize())
        );

        // 6. 转换为VO对象
        List<BookFilterVO> pageResults = booksPager.getResults().stream()
                .map(this::convertToBookFilterVO)
                .collect(Collectors.toList());

        // 7. 缓存分页结果
        BookFilterCache cacheData = new BookFilterCache();
        cacheData.setPageResults(pageResults);
        cacheData.setTotal((int) booksPager.getTotal());
        cacheData.setPageNumber(bookFilterDTO.getPageNumber());
        cacheData.setPageSize(bookFilterDTO.getPageSize());
        redisTemplate.opsForValue().set(cacheKey, cacheData, RedisKeyConstant.BOOK_FILTER_TTL, TimeUnit.SECONDS);

        // 8. 返回分页结果
        return convertCacheToPage(cacheData);
    }

    /**
     * 构建按收藏数量排序的查询
     */
    private QueryChain<Books> buildCollectionCountQuery(List<Integer> bookIds, BookFilterDTO bookFilterDTO) {
        // 1. 先获取所有符合条件的图书ID
        QueryChain<Books> queryChain = QueryChain.of(booksMapper)
                .ignoreNullValueInCondition(true)
                .ignoreEmptyInCondition(true)
                .trimStringInCondition(true);

        // 添加过滤条件
        if (bookIds != null) {
            queryChain.in(Books::getBookId, bookIds);
        }
        if (bookFilterDTO.getMinWordCount() != null) {
            queryChain.gte(Books::getWordCount, bookFilterDTO.getMinWordCount());
        }
        if (bookFilterDTO.getMaxWordCount() != null) {
            queryChain.lte(Books::getWordCount, bookFilterDTO.getMaxWordCount());
        }

        // 2. 获取这些图书的收藏数量
        List<Books> booksList = queryChain.list();
        Map<Integer, Long> collectionCountMap = usercollectionsService.getCollectionCounts(
                booksList.stream()
                        .map(Books::getBookId)
                        .collect(Collectors.toList())
        );

        // 3. 根据收藏数量排序
        booksList.sort((a, b) -> {
            Long countA = collectionCountMap.getOrDefault(a.getBookId(), 0L);
            Long countB = collectionCountMap.getOrDefault(b.getBookId(), 0L);
            int compare = countB.compareTo(countA); // 默认降序
            return bookFilterDTO.getOrderDirection() != null && bookFilterDTO.getOrderDirection() == 1 
                   ? -compare  // 升序
                   : compare;  // 降序
        });

        // 4. 构建最终查询，按排序后的ID顺序查询
        List<Integer> sortedBookIds = booksList.stream()
                .map(Books::getBookId)
                .collect(Collectors.toList());

        return QueryChain.of(booksMapper)
                .in(Books::getBookId, sortedBookIds)
                .orderBy(Books::getBookId); // 保持和sortedBookIds相同的顺序
    }

    /**
     * 构建按总字数排序的查询
     */
    private QueryChain<Books> buildWordCountQuery(List<Integer> bookIds, BookFilterDTO bookFilterDTO) {
        QueryChain<Books> queryChain = QueryChain.of(booksMapper)
                .ignoreNullValueInCondition(true)
                .ignoreEmptyInCondition(true)
                .trimStringInCondition(true);

        // 添加过滤条件
        if (bookIds != null) {
            queryChain.in(Books::getBookId, bookIds);
        }
        if (bookFilterDTO.getMinWordCount() != null) {
            queryChain.gte(Books::getWordCount, bookFilterDTO.getMinWordCount());
        }
        if (bookFilterDTO.getMaxWordCount() != null) {
            queryChain.lte(Books::getWordCount, bookFilterDTO.getMaxWordCount());
        }

        // 添加字数排序
        queryChain.orderBy(
                bookFilterDTO.getOrderDirection() != null && bookFilterDTO.getOrderDirection() == 1 
                ? OrderByDirection.ASC 
                : OrderByDirection.DESC,
                Books::getWordCount
        );

        return queryChain;
    }

    /**
     * 将缓存对象转换为分页对象
     */
    private Pager<BookFilterVO> convertCacheToPage(BookFilterCache cache) {
        Pager<BookFilterVO> pager = new Pager<>();
        pager.setResults(cache.getPageResults());
        pager.setTotal(cache.getTotal());
        pager.setNumber(cache.getPageNumber());
        pager.setSize(cache.getPageSize());
        return pager;
    }

    /**
     * 获取空的分页结果
     */
    private Pager<BookFilterVO> getEmptyPager(int pageNumber, int pageSize) {
        Pager<BookFilterVO> emptyPager = new Pager<>();
        emptyPager.setNumber(pageNumber);
        emptyPager.setSize(pageSize);
        emptyPager.setTotal(0);
        emptyPager.setResults(Collections.emptyList());
        return emptyPager;
    }

    /**
     * 将Books实体转换为BookFilterVO
     */
    private BookFilterVO convertToBookFilterVO(Books book) {
        BookFilterVO vo = new BookFilterVO();
        // 复制基本属性
        vo.setBookId(book.getBookId());
        vo.setTitle(book.getTitle());
        vo.setAuthor(book.getAuthor());
        vo.setCoverImage(book.getCoverImage());
        vo.setDescription(book.getDescription());
        vo.setWordCount(book.getWordCount());

        // 获取平均评分
        Double avgRating = userbookratingsService.getAverageRating(book.getBookId());
        vo.setAverageRating(avgRating != null ? avgRating : 0.0);

        return vo;
    }

    /**
     * 根据图书名搜索图书
     *
     * @param bookSearchDTO 搜索条件
     * @return 分页的图书信息
     */
    @Override
    public Pager<BookSearchVO> searchBooks(BookSearchDTO bookSearchDTO) {
        // 1. 构建查询条件
        QueryChain<Books> queryChain = QueryChain.of(booksMapper)
                .ignoreNullValueInCondition(true)
                .ignoreEmptyInCondition(true)
                .trimStringInCondition(true);

        // 2. 添加图书名称模糊查询条件
        if (bookSearchDTO.getKeyword() != null && !bookSearchDTO.getKeyword().trim().isEmpty()) {
            queryChain.like(Books::getTitle, bookSearchDTO.getKeyword());
        }

        // 3. 按热度降序排序
        queryChain.orderBy(OrderByDirection.DESC, Books::getPopularityScore);

        // 4. 执行分页查询
        Pager<Books> booksPager = queryChain.paging(
                Pager.of(bookSearchDTO.getPageNumber(), bookSearchDTO.getPageSize())
        );

        // 5. 转换为VO对象
        List<BookSearchVO> bookSearchVOList = booksPager.getResults().stream()
                .map(book -> {
                    BookSearchVO vo = new BookSearchVO();
                    // 复制基本属性
                    vo.setBookId(book.getBookId());
                    vo.setTitle(book.getTitle());
                    vo.setWordCount(book.getWordCount() != null ? book.getWordCount().intValue() : null);
                    vo.setAuthor(book.getAuthor());
                    vo.setDescription(book.getDescription());
                    vo.setPublishDate(book.getPublishDate());
                    vo.setCoverImage(book.getCoverImage());

                    // 查询并设置分类名称
                    String categoryName = getCategoryNameForBook(book.getBookId());
                    vo.setCategoryName(categoryName);

                    return vo;
                })
                .collect(Collectors.toList());

        // 6. 构建返回结果
        Pager<BookSearchVO> result = new Pager<>();
        result.setNumber(booksPager.getNumber());
        result.setSize(booksPager.getSize());
        result.setTotal(booksPager.getTotal());
        result.setResults(bookSearchVOList);

        return result;
    }

    /**
     * 获取作者的所有图书
     *
     * @param authorBooksDTO 查询条件
     * @return 作者图书分页信息
     */
    @Override
    public AuthorBooksPager getAuthorBooks(AuthorBooksDTO authorBooksDTO) {
        // 1. 构建查询条件
        QueryChain<Books> queryChain = QueryChain.of(booksMapper)
                .ignoreNullValueInCondition(true)
                .ignoreEmptyInCondition(true)
                .trimStringInCondition(true)
                .eq(Books::getAuthor, authorBooksDTO.getAuthor())
                .orderBy(OrderByDirection.DESC, Books::getPopularityScore);

        // 2. 执行分页查询
        Pager<Books> booksPager = queryChain.paging(
                Pager.of(authorBooksDTO.getPageNumber(), authorBooksDTO.getPageSize())
        );

        // 3. 转换为VO对象
        List<BookSearchVO> bookSearchVOList = booksPager.getResults().stream()
                .map(book -> {
                    BookSearchVO vo = new BookSearchVO();
                    // 复制基本属性
                    vo.setBookId(book.getBookId());
                    vo.setTitle(book.getTitle());
                    vo.setWordCount(book.getWordCount() != null ? book.getWordCount().intValue() : null);
                    vo.setAuthor(book.getAuthor());
                    vo.setDescription(book.getDescription());
                    vo.setPublishDate(book.getPublishDate());
                    vo.setCoverImage(book.getCoverImage());

                    // 查询并设置分类名称
                    String categoryName = getCategoryNameForBook(book.getBookId());
                    vo.setCategoryName(categoryName);

                    return vo;
                })
                .collect(Collectors.toList());

        // 4. 构建返回结果
        AuthorBooksPager result = new AuthorBooksPager();
        result.setResults(bookSearchVOList);
        result.setTotal((int) booksPager.getTotal());
        result.setNumber(booksPager.getNumber());
        result.setSize(booksPager.getSize());
        result.setTotalPage((int) Math.ceil((double) booksPager.getTotal() / booksPager.getSize()));

        return result;
    }

    private BooksVO convertToBooksPageVO(Books book) {
        BooksVO booksVO = new BooksVO();
        BeanUtils.copyProperties(book, booksVO);

        // 查询该书的单个分类名称
        String categoryName = getCategoryNameForBook(book.getBookId());
        // 设置分类名称
        booksVO.setCategoryName(categoryName);

        return booksVO;
    }

    private String getCategoryNameForBook(Integer bookId) {
        // 通过 Book categories 表获取该书的分类 ID
        Bookcategories bookCategory = QueryChain.of(bookcategoriesMapper)
                .select(Bookcategories.class)
                .eq(Bookcategories::getBookId, bookId) // 根据 bookId 查找关联的分类
                .returnType(Bookcategories.class)
                .get(); // 返回单个结果

        if (bookCategory != null) {
            // 如果存在关联的分类，查询分类名称
            Categories category = categoriesMapper.get(where ->
                    where.eq(Categories::getCategoryId, bookCategory.getCategoryId()));

            // 返回分类名称
            return category != null ? category.getCategoryName() : "";
        }

        // 如果没有找到分类，返回空字符串
        return "";
    }

    /**
     * 获取热门书籍排行榜
     * @param hotBooksDTO 分页参数
     * @return 热门书籍分页数据
     */
    @Override
    public Pager<HotBooksVO> getHotBooks(HotBooksDTO hotBooksDTO) {
        // 1. 构建查询条件，按热度值降序排序
        QueryChain<Books> queryChain = QueryChain.of(booksMapper)
                .ignoreNullValueInCondition(true)
                .ignoreEmptyInCondition(true)
                .trimStringInCondition(true)
                .orderBy(OrderByDirection.DESC, Books::getPopularityScore);

        // 2. 执行分页查询
        Pager<Books> booksPager = queryChain.paging(
                Pager.of(hotBooksDTO.getPage(), hotBooksDTO.getPageSize())
        );

        // 3. 转换为 VO 对象
        List<HotBooksVO> hotBooksVOList = booksPager.getResults().stream()
                .map(book -> {
                    HotBooksVO vo = new HotBooksVO();
                    vo.setId(book.getBookId());
                    vo.setTitle(book.getTitle());
                    vo.setAuthor(book.getAuthor());
                    vo.setWordCount(book.getWordCount() != null ? book.getWordCount().intValue() : null);
                    vo.setDescription(book.getDescription());
                    vo.setCoverUrl(book.getCoverImage());
                    vo.setHotDegree(book.getPopularityScore());
                    
                    // 转换 Date 为 LocalDateTime
                    if (book.getPublishDate() != null) {
                        vo.setPublishDate(LocalDateTime.ofInstant(
                            book.getPublishDate().toInstant(),
                            ZoneId.systemDefault()
                        ));
                    }
                    
                    // 获取分类名称
                    String categoryName = getCategoryNameForBook(book.getBookId());
                    vo.setCategory(categoryName);
                    
                    return vo;
                })
                .collect(Collectors.toList());

        // 4. 构建返回结果
        Pager<HotBooksVO> result = new Pager<>();
        result.setNumber(booksPager.getNumber());
        result.setSize(booksPager.getSize());
        result.setTotal(booksPager.getTotal());
        result.setResults(hotBooksVOList);

        return result;
    }

}
